﻿using System;
using System.Net;
using System.Net.Http;
using System.Runtime.InteropServices;
using System.Threading.Tasks;

using Newtonsoft.Json.Linq;

namespace Utils.Adapter
{
    public class IpPlaceAdapter : IDisposable
    {
        private readonly HttpClient httpClient;

        private readonly ICacheStrategy cacheStrategy;
        public IpPlaceAdapter(HttpClient httpClient, ICacheStrategy cacheStrategy)
        {
            this.httpClient = httpClient;
            this.cacheStrategy = cacheStrategy;
        }

        public async Task<(string province, string city, string region)> GetRegion(string ip)
        {
            if (IsPrivateNetwork3(ip))
            {
                throw Error.DefaultError("局域网IP");
            }
            var url = new Uri($"http://whois.pconline.com.cn/ipJson.jsp?ip={ip}&json=true");
            var result = await httpClient.GetAsync(url).ReadAsJTokenAsync();
            string region = result["region"].Value<string>();
            string city = result["city"].Value<string>();
            string province = result["pro"].Value<string>();
            return (province, city, region);
        }

        bool IsPrivateNetwork3(string ipv4Address)
        {
            if (IPAddress.TryParse(ipv4Address, out var ip))
            {
                byte[] ipBytes = ip.GetAddressBytes();
                if (ipBytes[0] == 10) return true;
                if (ipBytes[0] == 172 && ipBytes[1] >= 16 && ipBytes[1] <= 31) return true;
                if (ipBytes[0] == 192 && ipBytes[1] == 168) return true;
            }
            return false;
        }

        public async Task<JToken> TMap(JObject obj)
        {

            string key = "FLEBZ-3NGW3-RJX3N-3SH4C-WQFRF-V6FMQ";
            string path = obj["_path"].ToString();
            string url = $"https://apis.map.qq.com/ws/{path}?key={key}";
            foreach (var item in obj)
            {
                if (item.Key == "_path")
                {
                    continue;
                }
                url += $"&{item.Key}={item.Value}";
            }
            return await httpClient.GetAsync(url).ReadAsJTokenAsync();
        }
        public async Task<JObject> GetLocation(string ip)
        {
            if (IsPrivateNetwork3(ip))
            {
                ip = "";
            }
            string key = "FLEBZ-3NGW3-RJX3N-3SH4C-WQFRF-V6FMQ";
            string url = $"https://apis.map.qq.com/ws/location/v1/ip?key={key}&output=JSON&ip={ip}";
            var resp = await httpClient.GetAsync(url).ReadAsJTokenAsync();
            if (resp.Value<int>("status") != 0)
            {
                throw new ThirdException(resp.Value<int>("status").ToString(), resp["message"].ToString());
            }
            return (JObject)resp["result"];
        }

        public Task<JObject> GetLocationByCache(string ip)
        {
            return cacheStrategy.GetOrCreateAsync("IpLocation:" + ip, () => GetLocation(ip), 600);
        }

        public async Task<string> GetCity(string ip)
        {
            var (province, city, area) = await GetRegion(ip);
            return (province.IfNullOrEmpty("", "{0} ") + city.IfNullOrEmpty("", "{0} ") + area.IfNullOrEmpty("")).IfNullOrEmpty("未知");
        }

        public async Task<string> GetCityBayCache(string ip)
        {
            return await cacheStrategy.GetOrCreateAsync("IpPlace:" + ip, () => GetCity(ip), 600);
        }

        public void Dispose()
        {
            httpClient.Dispose();
        }
    }
}
